﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using RioTinto.Data.Interfaces;
using RioTinto.Data.Entities;

namespace RioTinto.Data.Test
{
    /// <summary>
    /// A mock DataManager class used for automated unit testing
    /// to allow isolation of business logic from data access
    /// logic.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MockDataManager<T> : IDataManager<T> where T : BaseEntity<T>
    {
        private IList<T> m_data = new List<T>();

        public MockDataManager()
        {
            return;
        }

        #region IDataManager<T> Members

        public T Save(T entity)
        {
            Int32 id = BaseEntity<T>.GetPrimaryKeyValue(entity);

            if (id <= default(Int32))
            {
                BaseEntity<T>.SetPrimaryKeyValue(entity, m_data.Count);
                m_data.Add(entity);
            }
            else
            {
                Int32 index = id - 1;
                m_data[index] = entity;
            }

            return entity;
        }

        public void SaveAll(IEnumerable<T> list)
        {
            foreach (T item in list)
                Save(item);
        }

        public void Delete(T entity)
        {
            Int32 id = BaseEntity<T>.GetPrimaryKeyValue(entity);
            Delete(id);
        }

        public void Delete(int id)
        {
            if (id <= default(Int32))
                return;

            Int32 index = id - 1;

            m_data.RemoveAt(index);
        }

        public void DeleteAll(IEnumerable<T> list)
        {
            foreach (T item in list)
                Delete(item);
        }

        public T GetOne(int id)
        {
            if (id <= default(Int32))
                return null;

            Int32 index = id - 1;

            return m_data[index];
        }

        public void Refresh(T entity)
        {
            throw new NotImplementedException();
        }

        public IList<T> GetAll()
        {
            return m_data;
        }

        public IList<T> GetAll(Expression<Func<T, bool>> predicate)
        {
            return m_data.AsQueryable<T>().Where(predicate).ToList();
        }

        public IQueryable<T> GetQueryable(Expression<Func<T, bool>> predicate)
        {
            return m_data.AsQueryable<T>().Where(predicate);
        }

        public IQueryable<T> GetQueryable()
        {
            return m_data.AsQueryable<T>();
        }
        #endregion
    }
}
